function TSMC_Derive_Street_Masks

 
 % FILE INPUT SETTINGS %
InputDirectory='C:\Users\Les Frackowiak\Desktop\Tests\TSMC\Street Detection Samples\';
OutputDirectory='C:\Users\Les Frackowiak\Desktop\Tests\TSMC\Street Detection Samples\Output\';
ImagePreffix='';
ImageSuffix='-G.jpg';
StartFile=1;
EndFile=100;



% IMAGE PREPROCESSING SETTINGS %
BACKGROUND_EQUALIZATION=1;
BACKGROUND_EQUALIZATION_SIZE=101;
BACKGROUND_EQUALIZATION_SIGMA=51;
GRAYSCALE_STANDARDIZATION=1;
GRAYSCALE_STANDARDIZATION_VALUE=130;
USE_MEAN_FROM_ORIGINAL_IMAGE=1;
GRAYSCALE_THRESHOLD=50;




% STREET SETTINGS %
NUMBER_OF_X_BLOCKS=3;
NUMBER_OF_Y_BLOCKS=3;
PEAKS_DELTA_MAX=10;
MIN_STREET_WIDTH=20;
MAX_STREET_WIDTH=150;
MINIMA_THRESHOLD=20;
MAX_CENTERS_DISTANCE=50;
RHO_RESOLUTION=0.5;
THETA_RESOLUTION=0.5;
NUMBER_OF_HOUGH_PEAKS=8;
HOUGH_FILLGAP_SPACING=10;
HOUGH_MIN_LINE_LENGTH=150;
DELTA_HEIGHT=10;

% HORIZONTAL STREET SETTINGS %
HS_THETA_START=-90;
HS_THETA_END=-85;

% VERTICAL STREET SETTINGS %
VS_THETA_START=-10;
VS_THETA_END=10;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% CODE START %
if ~exist(char(OutputDirectory),'dir')
    mkdir(char(OutputDirectory));
end
ImageNumber=0;
for k=StartFile:EndFile
    if exist([char(InputDirectory),int2str(k),char(ImageSuffix)],'file')
        ImageNumber=ImageNumber+1;
        Data.Image{ImageNumber}=imread([char(InputDirectory),char(ImagePreffix),int2str(k),char(ImageSuffix)]);
        Data.Index{ImageNumber}=k;
    end
end
for k=1:ImageNumber
    Gray=Data.Image{k};
    if size(size(Gray),2)==3
        Gray=rgb2gray(Gray);
    end
    [ImageHeight,ImageWidth]=size(Gray);
    if USE_MEAN_FROM_ORIGINAL_IMAGE
        AverageValue=mean2(Gray);
    end
    if BACKGROUND_EQUALIZATION
        Filter=fspecial('gaussian',BACKGROUND_EQUALIZATION_SIZE,BACKGROUND_EQUALIZATION_SIGMA);
        Filtered=imfilter(Gray,Filter,'symmetric');
        Filtered_Min=min(min(Filtered));
        Gray=Gray-(Filtered-Filtered_Min);
    end
    if GRAYSCALE_STANDARDIZATION
        if ~USE_MEAN_FROM_ORIGINAL_IMAGE
            AverageValue=mean2(Gray);
        end
        Gray=Gray*(GRAYSCALE_STANDARDIZATION_VALUE/AverageValue);
    end
    Binary_Image=1-im2bw(Gray,GRAYSCALE_THRESHOLD/255);
    HS_Street_Mask=false(ImageHeight,ImageWidth);
    VS_Street_Mask=false(ImageHeight,ImageWidth);
    
    
    
    % HORIZONTAL STREET DETECTION %
    HS_STD_Y_Vector=zeros(NUMBER_OF_X_BLOCKS,ImageHeight);
    HS_X_BLOCKS=floor(ImageWidth/NUMBER_OF_X_BLOCKS);
    for j=1:NUMBER_OF_Y_BLOCKS
        X_Min=1+(j-1)*HS_X_BLOCKS;
        X_Max=X_Min+HS_X_BLOCKS;
        if X_Max>ImageWidth
            X_Max=ImageWidth;
        end
        Sample=double(Gray(:,X_Min:X_Max));
        HS_STD_Y_Vector(j,:)=std(Sample,0,2);
    end
    HS_Possible_Street_Count=0;
    HS_Possible_Vector=zeros(1,2);
    for j=1:NUMBER_OF_X_BLOCKS
        Sample=HS_STD_Y_Vector(j,:);
        [Min_Value_A,Min_Index_A]=min(Sample);
        if Min_Value_A<=MINIMA_THRESHOLD
            StartIndex=Min_Index_A-MAX_STREET_WIDTH;
            EndIndex=Min_Index_A-MIN_STREET_WIDTH;
            if StartIndex<1
                StartIndex=1;
            end
            [HS_Left_Minimum_Value,HS_Left_Minimum_Index]=min(Sample(1,StartIndex:EndIndex));
            HS_Left_Minimum_Index=HS_Left_Minimum_Index+StartIndex-1;
            StartIndex=Min_Index_A+MIN_STREET_WIDTH;
            EndIndex=Min_Index_A+MAX_STREET_WIDTH;
            if EndIndex>ImageHeight
                EndIndex=ImageHeight;
            end
            [HS_Right_Minimum_Value,HS_Right_Minimum_Index]=min(Sample(1,StartIndex:EndIndex));
            HS_Right_Minimum_Index=HS_Right_Minimum_Index+StartIndex-1;
            if HS_Left_Minimum_Value<HS_Right_Minimum_Value
                Min_Value_B=HS_Left_Minimum_Value;
                Min_Index_B=HS_Left_Minimum_Index;
            else
                Min_Value_B=HS_Right_Minimum_Value;
                Min_Index_B=HS_Right_Minimum_Index;
            end
            if abs(Min_Value_A-Min_Value_B)<PEAKS_DELTA_MAX
                if Min_Index_A<Min_Index_B
                    HS_Start=Min_Index_A;
                    HS_End=Min_Index_B;
                else
                    HS_Start=Min_Index_B;
                    HS_End=Min_Index_A;
                end
                HS_Possible_Street_Count=HS_Possible_Street_Count+1;
                HS_Possible_Vector(HS_Possible_Street_Count,1)=HS_Start;
                HS_Possible_Vector(HS_Possible_Street_Count,2)=HS_End;
            end
        end
    end
    HS_Start=2;
    HS_End=1;
    if HS_Possible_Street_Count==1
        HS_Start=HS_Possible_Vector(1,1);
        HS_End=HS_Possible_Vector(1,2);
    elseif HS_Possible_Street_Count>1
        HS_Mean_Vector=0.5*(HS_Possible_Vector(:,1)+HS_Possible_Vector(:,2));
        HS_Mean_Range=range(HS_Mean_Vector);
        if HS_Mean_Range>MAX_CENTERS_DISTANCE
            HS_Possible_Street_Count=0;
        else
            HS_Start=min(HS_Possible_Vector(:,1));
            HS_End=max(HS_Possible_Vector(:,2));
        end
    end
    if HS_Possible_Street_Count>0
        [Hough_Transform_Matrix,THETA,RHO]=hough(Binary_Image,'RhoResolution',RHO_RESOLUTION,'Theta',HS_THETA_START:THETA_RESOLUTION:HS_THETA_END);
        HS_Hough_Peaks=houghpeaks(Hough_Transform_Matrix,NUMBER_OF_HOUGH_PEAKS);
        HS_Hough_Lines=houghlines(Binary_Image,THETA,RHO,HS_Hough_Peaks,'FillGap',HOUGH_FILLGAP_SPACING,'MinLength',HOUGH_MIN_LINE_LENGTH);
        HS_Number_Of_Hough_Lines=size(HS_Hough_Lines,2);
        HS_Check_Start=0;
        HS_Check_End=0;
        for h=1:HS_Number_Of_Hough_Lines
            Point_1=HS_Hough_Lines(h).point1;
            Point_2=HS_Hough_Lines(h).point2;
            Average_Point=.5*(Point_1(2)+Point_2(2));
            if abs(Average_Point-HS_Start)<DELTA_HEIGHT
                HS_Check_Start=1;
            end
            if abs(Average_Point-HS_End)<DELTA_HEIGHT
                HS_Check_End=1;
            end
        end
        if HS_Check_Start && HS_Check_End
            HS_Street_Mask(HS_Start:HS_End,:)=1; 
        end
    end
    
    
    
    % VERTICAL STREET DETECTION %
    VS_STD_X_Vector=zeros(NUMBER_OF_Y_BLOCKS,ImageWidth);
    VS_Y_BLOCKS=floor(ImageHeight/NUMBER_OF_Y_BLOCKS);
    for i=1:NUMBER_OF_X_BLOCKS
        Y_Min=1+(i-1)*VS_Y_BLOCKS;
        Y_Max=Y_Min+VS_Y_BLOCKS;
        if Y_Max>ImageHeight
            Y_Max=ImageHeight;
        end
        Sample=double(Gray(Y_Min:Y_Max,:));
        VS_STD_X_Vector(i,:)=std(Sample,0,1);
    end
    VS_Possible_Street_Count=0;
    VS_Possible_Vector=zeros(1,2);
    for i=1:NUMBER_OF_Y_BLOCKS
        Sample=VS_STD_X_Vector(i,:);
        [Min_Value_A,Min_Index_A]=min(Sample);
        if Min_Value_A<=MINIMA_THRESHOLD
            StartIndex=Min_Index_A-MAX_STREET_WIDTH;
            EndIndex=Min_Index_A-MIN_STREET_WIDTH;
            if StartIndex<1
                StartIndex=1;
            end
            [VS_Left_Minimum_Value,VS_Left_Minimum_Index]=min(Sample(1,StartIndex:EndIndex));
            VS_Left_Minimum_Index=VS_Left_Minimum_Index+StartIndex-1;
            StartIndex=Min_Index_A+MIN_STREET_WIDTH;
            EndIndex=Min_Index_A+MAX_STREET_WIDTH;
            if EndIndex>ImageWidth
                EndIndex=ImageWidth;
            end
            [VS_Right_Minimum_Value,VS_Right_Minimum_Index]=min(Sample(1,StartIndex:EndIndex));
            VS_Right_Minimum_Index=VS_Right_Minimum_Index+StartIndex-1;
            if VS_Left_Minimum_Value<VS_Right_Minimum_Value
                Min_Value_B=VS_Left_Minimum_Value;
                Min_Index_B=VS_Left_Minimum_Index;
            else
                Min_Value_B=VS_Right_Minimum_Value;
                Min_Index_B=VS_Right_Minimum_Index;
            end
            if abs(Min_Value_A-Min_Value_B)<PEAKS_DELTA_MAX
                if Min_Index_A<Min_Index_B
                    VS_Start=Min_Index_A;
                    VS_End=Min_Index_B;
                else
                    VS_Start=Min_Index_B;
                    VS_End=Min_Index_A;
                end
                VS_Possible_Street_Count=VS_Possible_Street_Count+1;
                VS_Possible_Vector(VS_Possible_Street_Count,1)=VS_Start;
                VS_Possible_Vector(VS_Possible_Street_Count,2)=VS_End;
            end
        end
    end
    VS_Start=2;
    VS_End=1;
    if VS_Possible_Street_Count==1
        VS_Start=VS_Possible_Vector(1,1);
        VS_End=VS_Possible_Vector(1,2);
    elseif VS_Possible_Street_Count>1
        VS_Mean_Vector=0.5*(VS_Possible_Vector(:,1)+VS_Possible_Vector(:,2));
        VS_Mean_Range=range(VS_Mean_Vector);
        if VS_Mean_Range>MAX_CENTERS_DISTANCE
            VS_Possible_Street_Count=0;
        else
            VS_Start=min(VS_Possible_Vector(:,1));
            VS_End=max(VS_Possible_Vector(:,2));
        end
    end
    if VS_Possible_Street_Count>0
        [Hough_Transform_Matrix,THETA,RHO]=hough(Binary_Image,'RhoResolution',RHO_RESOLUTION,'Theta',VS_THETA_START:THETA_RESOLUTION:VS_THETA_END);
        VS_Hough_Peaks=houghpeaks(Hough_Transform_Matrix,NUMBER_OF_HOUGH_PEAKS);
        VS_Hough_Lines=houghlines(Binary_Image,THETA,RHO,VS_Hough_Peaks,'FillGap',HOUGH_FILLGAP_SPACING,'MinLength',HOUGH_MIN_LINE_LENGTH);
        VS_Number_Of_Hough_Lines=size(VS_Hough_Lines,2);
        VS_Check_Start=0;
        VS_Check_End=0;
        for h=1:VS_Number_Of_Hough_Lines
            Point_1=VS_Hough_Lines(h).point1;
            Point_2=VS_Hough_Lines(h).point2;
            Average_Point=.5*(Point_1(1)+Point_2(1));
            if abs(Average_Point-VS_Start)<DELTA_HEIGHT
                VS_Check_Start=1;
            end
            if abs(Average_Point-VS_End)<DELTA_HEIGHT
                VS_Check_End=1;
            end
        end
        if VS_Check_Start && VS_Check_End
            VS_Street_Mask(:,VS_Start:VS_End)=1; 
        end
    end
    
    
    
    % OUTPUT RESULT %
    Street_Mask=HS_Street_Mask+VS_Street_Mask;
    Image=Data.Image{k};
    Image(:,:,1)=Image(:,:,1).*uint8(1-Street_Mask)+255*uint8(Street_Mask);
    imwrite(Image,[char(OutputDirectory),int2str(Data.Index{k}),'_Output.jpg'],'jpg');
end
end










